home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / orca / orca.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  33.4 KB  |  1,167 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''The main module for the Orca screen reader.'''
  5. __id__ = '$Id: orca.py 4285 2008-10-12 20:42:37Z wwalker $'
  6. __version__ = '$Revision: 4285 $'
  7. __date__ = '$Date: 2008-10-12 16:42:37 -0400 (Sun, 12 Oct 2008) $'
  8. __copyright__ = 'Copyright (c) 2004-2008 Sun Microsystems Inc.'
  9. __license__ = 'LGPL'
  10. import sys
  11. sys.argv[0] = 'orca'
  12. import pygtk
  13. pygtk.require('2.0')
  14.  
  15. try:
  16.     import gtk
  17. except:
  18.     pass
  19.  
  20.  
  21. try:
  22.     import mouse_review
  23. except RuntimeError:
  24.     pass
  25.  
  26. import getopt
  27. import gnome
  28. import os
  29. import signal
  30. import time
  31. import unicodedata
  32. import pyatspi
  33. import braille
  34. import debug
  35. import httpserver
  36. import keynames
  37. import keybindings
  38. import mag
  39. import orca_state
  40. import platform
  41. import settings
  42. import speech
  43. from input_event import BrailleEvent
  44. from input_event import KeyboardEvent
  45. from input_event import MouseButtonEvent
  46. from input_event import keyEventToString
  47. if settings.useDBus:
  48.     import dbusserver
  49.  
  50. from orca_i18n import _
  51. if settings.debugMemoryUsage:
  52.     import gc
  53.     gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_COLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS | gc.DEBUG_SAVEALL)
  54.  
  55. _userSettings = None
  56. _commandLineSettings = { }
  57. _PRESENTATION_MANAGERS = None
  58. _currentPresentationManager = -1
  59.  
  60. def _switchToPresentationManager(index):
  61.     '''Switches to the given presentation manager.
  62.  
  63.     Arguments:
  64.     - index: an index into _PRESENTATION_MANAGERS
  65.     '''
  66.     global _currentPresentationManager, _currentPresentationManager, _currentPresentationManager
  67.     if _currentPresentationManager >= 0:
  68.         _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()
  69.     
  70.     _currentPresentationManager = index
  71.     if _currentPresentationManager >= len(_PRESENTATION_MANAGERS):
  72.         _currentPresentationManager = 0
  73.     elif _currentPresentationManager < 0:
  74.         _currentPresentationManager = len(_PRESENTATION_MANAGERS) - 1
  75.     
  76.     _PRESENTATION_MANAGERS[_currentPresentationManager].activate()
  77.  
  78.  
  79. def _switchToNextPresentationManager(script = None, inputEvent = None):
  80.     '''Switches to the next presentation manager.
  81.  
  82.     Arguments:
  83.     - inputEvent: the InputEvent instance that caused this to be called.
  84.  
  85.     Returns True indicating the event should be consumed.
  86.     '''
  87.     _switchToPresentationManager(_currentPresentationManager + 1)
  88.     return True
  89.  
  90.  
  91. def getScriptForApp(app):
  92.     '''Get the script for the given application object from the current
  93.     presentation manager.
  94.  
  95.     Arguments:
  96.     - app: An application accessible.
  97.  
  98.     Returns a Script instance.
  99.     '''
  100.     script = None
  101.     if _currentPresentationManager >= 0:
  102.         script = _PRESENTATION_MANAGERS[_currentPresentationManager].getScript(app)
  103.     
  104.     return script
  105.  
  106.  
  107. def setLocusOfFocus(event, obj, notifyPresentationManager = True):
  108.     '''Sets the locus of focus (i.e., the object with visual focus) and
  109.     notifies the current presentation manager of the change.
  110.  
  111.     Arguments:
  112.     - event: if not None, the Event that caused this to happen
  113.     - obj: the Accessible with the new locus of focus.
  114.     - notifyPresentationManager: if True, propagate this event
  115.     '''
  116.     if obj == orca_state.locusOfFocus:
  117.         return None
  118.     oldLocusOfFocus = orca_state.locusOfFocus
  119.     
  120.     try:
  121.         oldLocusOfFocus.getRole()
  122.     except:
  123.         None if event and event.source and event.host_application and orca_state.activeScript else obj == orca_state.locusOfFocus
  124.         oldLocusOfFocus = None
  125.  
  126.     orca_state.focusHistory = orca_state.focusHistory[:settings.focusHistoryLength - 1]
  127.     orca_state.focusHistory.insert(0, oldLocusOfFocus)
  128.     orca_state.locusOfFocus = obj
  129.     
  130.     try:
  131.         app = orca_state.locusOfFocus.getApplication()
  132.     except:
  133.         None if event and event.source and event.host_application and orca_state.activeScript else obj == orca_state.locusOfFocus
  134.         orca_state.locusOfFocus = None
  135.         if event:
  136.             debug.println(debug.LEVEL_FINE, "LOCUS OF FOCUS: None event='%s'" % event.type)
  137.         else:
  138.             debug.println(debug.LEVEL_FINE, 'LOCUS OF FOCUS: None event=None')
  139.  
  140.     if not app:
  141.         appname = 'None'
  142.     else:
  143.         appname = "'" + app.name + "'"
  144.     debug.println(debug.LEVEL_FINE, "LOCUS OF FOCUS: app=%s name='%s' role='%s'" % (appname, orca_state.locusOfFocus.name, orca_state.locusOfFocus.getRoleName()))
  145.     if event:
  146.         debug.println(debug.LEVEL_FINE, "                event='%s'" % event.type)
  147.     else:
  148.         debug.println(debug.LEVEL_FINE, '                event=None')
  149.     if notifyPresentationManager and _currentPresentationManager >= 0:
  150.         _PRESENTATION_MANAGERS[_currentPresentationManager].locusOfFocusChanged(event, oldLocusOfFocus, orca_state.locusOfFocus)
  151.     
  152.  
  153.  
  154. def visualAppearanceChanged(event, obj):
  155.     """Called (typically by scripts) when the visual appearance of an object
  156.     changes and notifies the current presentation manager of the change.  This
  157.     method should not be called for objects whose visual appearance changes
  158.     solely because of focus -- setLocusOfFocus is used for that.  Instead, it
  159.     is intended mostly for objects whose notional 'value' has changed, such as
  160.     a checkbox changing state, a progress bar advancing, a slider moving, text
  161.     inserted, caret moved, etc.
  162.  
  163.     Arguments:
  164.     - event: if not None, the Event that caused this to happen
  165.     - obj: the Accessible whose visual appearance changed.
  166.     """
  167.     if _currentPresentationManager >= 0:
  168.         _PRESENTATION_MANAGERS[_currentPresentationManager].visualAppearanceChanged(event, obj)
  169.     
  170.  
  171.  
  172. def _onChildrenChanged(e):
  173.     '''Tracks children-changed events on the desktop to determine when
  174.     apps start and stop.
  175.  
  176.     Arguments:
  177.     - e: at-spi event from the at-api registry
  178.     '''
  179.     desktop = pyatspi.Registry.getDesktop(0)
  180.     if e.source == desktop:
  181.         
  182.         try:
  183.             if desktop.childCount == 0:
  184.                 speech.speak(_('Goodbye.'))
  185.                 shutdown()
  186.                 return None
  187.         debug.printException(debug.LEVEL_FINEST)
  188.         shutdown()
  189.         return None
  190.  
  191.     
  192.  
  193.  
  194. def _onMouseButton(e):
  195.     '''Tracks mouse button events, stopping any speech in progress.
  196.  
  197.     Arguments:
  198.     - e: at-spi event from the at-api registry
  199.     '''
  200.     mouse_event = MouseButtonEvent(e)
  201.     orca_state.lastInputEvent = mouse_event
  202.     if mouse_event.pressed:
  203.         speech.stop()
  204.     
  205.  
  206.  
  207. def cycleDebugLevel(script = None, inputEvent = None):
  208.     levels = [
  209.         debug.LEVEL_ALL,
  210.         'all',
  211.         debug.LEVEL_FINEST,
  212.         'finest',
  213.         debug.LEVEL_FINER,
  214.         'finer',
  215.         debug.LEVEL_FINE,
  216.         'fine',
  217.         debug.LEVEL_CONFIGURATION,
  218.         'configuration',
  219.         debug.LEVEL_INFO,
  220.         'info',
  221.         debug.LEVEL_WARNING,
  222.         'warning',
  223.         debug.LEVEL_SEVERE,
  224.         'severe',
  225.         debug.LEVEL_OFF,
  226.         'off']
  227.     
  228.     try:
  229.         levelIndex = levels.index(debug.debugLevel) + 2
  230.     except:
  231.         levelIndex = 0
  232.  
  233.     if levelIndex >= len(levels):
  234.         levelIndex = 0
  235.     
  236.     debug.debugLevel = levels[levelIndex]
  237.     speech.speak('Debug level %s.' % levels[levelIndex + 1])
  238.     return True
  239.  
  240.  
  241. def exitLearnMode(self, inputEvent = None):
  242.     '''Turns learn mode off.
  243.  
  244.     Returns True to indicate the input event has been consumed.
  245.     '''
  246.     message = _('Exiting learn mode.')
  247.     speech.speak(message)
  248.     braille.displayMessage(message)
  249.     settings.learnModeEnabled = False
  250.     return True
  251.  
  252. _keyBindings = None
  253. _orcaModifierPressed = False
  254.  
  255. def isPrintableKey(event_string):
  256.     '''Return an indication of whether this is an alphanumeric or
  257.        punctuation key.
  258.  
  259.     Arguments:
  260.     - event: the event string
  261.  
  262.     Returns True if this is an alphanumeric or punctuation key.
  263.     '''
  264.     if event_string == 'space':
  265.         reply = True
  266.     else:
  267.         unicodeString = event_string.decode('UTF-8')
  268.         if not len(unicodeString) == 1 and unicodeString.isalnum() and unicodeString.isspace():
  269.             pass
  270.         reply = unicodedata.category(unicodeString)[0] in ('P', 'S')
  271.     debug.println(debug.LEVEL_FINEST, 'orca.isPrintableKey: returning: %s' % reply)
  272.     return reply
  273.  
  274.  
  275. def isModifierKey(event_string):
  276.     '''Return an indication of whether this is a modifier key.
  277.  
  278.     Arguments:
  279.     - event: the event string
  280.  
  281.     Returns True if this is a modifier key
  282.     '''
  283.     modifierKeys = [
  284.         'Alt_L',
  285.         'Alt_R',
  286.         'Control_L',
  287.         'Control_R',
  288.         'Shift_L',
  289.         'Shift_R',
  290.         'Meta_L',
  291.         'Meta_R']
  292.     modifierKeys.extend(settings.orcaModifierKeys)
  293.     reply = event_string in modifierKeys
  294.     debug.println(debug.LEVEL_FINEST, 'orca.isModifierKey: returning: %s' % reply)
  295.     return reply
  296.  
  297.  
  298. def isLockingKey(event_string):
  299.     '''Return an indication of whether this is a locking key.
  300.  
  301.     Arguments:
  302.     - event: the event string
  303.  
  304.     Returns True if this is a locking key.
  305.     '''
  306.     lockingKeys = [
  307.         'Caps_Lock',
  308.         'Num_Lock',
  309.         'Scroll_Lock']
  310.     if event_string in lockingKeys:
  311.         pass
  312.     reply = event_string not in settings.orcaModifierKeys
  313.     debug.println(debug.LEVEL_FINEST, 'orca.isLockingKey: returning: %s' % reply)
  314.     return reply
  315.  
  316.  
  317. def isFunctionKey(event_string):
  318.     '''Return an indication of whether this is a function key.
  319.  
  320.     Arguments:
  321.     - event: the event string
  322.  
  323.     Returns True if this is a function key.
  324.     '''
  325.     functionKeys = [
  326.         'F1',
  327.         'F2',
  328.         'F3',
  329.         'F4',
  330.         'F5',
  331.         'F6',
  332.         'F7',
  333.         'F8',
  334.         'F9',
  335.         'F10',
  336.         'F11',
  337.         'F12']
  338.     reply = event_string in functionKeys
  339.     debug.println(debug.LEVEL_FINEST, 'orca.isFunctionKey: returning: %s' % reply)
  340.     return reply
  341.  
  342.  
  343. def isActionKey(event_string):
  344.     '''Return an indication of whether this is an action key.
  345.  
  346.     Arguments:
  347.     - event: the event string
  348.  
  349.     Returns True if this is an action key.
  350.     '''
  351.     actionKeys = [
  352.         'Return',
  353.         'Escape',
  354.         'Tab',
  355.         'BackSpace',
  356.         'Delete',
  357.         'Page_Up',
  358.         'Page_Down',
  359.         'Home',
  360.         'End']
  361.     reply = event_string in actionKeys
  362.     debug.println(debug.LEVEL_FINEST, 'orca.isActionKey: returning: %s' % reply)
  363.     return reply
  364.  
  365.  
  366. def isNavigationKey(event_string):
  367.     '''Return an indication of whether this is a navigation (arrow) key
  368.     or if the user has the Orca modifier key held done.
  369.  
  370.     Arguments:
  371.     - event: the event string
  372.     - modifiers: key modifiers state
  373.  
  374.     Returns True if this is a navigation key.
  375.     '''
  376.     navigationKeys = [
  377.         'Left',
  378.         'Right',
  379.         'Up',
  380.         'Down']
  381.     if not event_string in navigationKeys:
  382.         pass
  383.     reply = _orcaModifierPressed
  384.     debug.println(debug.LEVEL_FINEST, 'orca.isNavigationKey: returning: %s' % reply)
  385.     return reply
  386.  
  387.  
  388. class KeyEventType:
  389.     '''Definition of available key event types.'''
  390.     PRINTABLE = 'PRINTABLE'
  391.     MODIFIER = 'MODIFIER'
  392.     LOCKING = 'LOCKING'
  393.     LOCKING_LOCKED = 'LOCKING_LOCKED'
  394.     LOCKING_UNLOCKED = 'LOCKING_UNLOCKED'
  395.     FUNCTION = 'FUNCTION'
  396.     ACTION = 'ACTION'
  397.     NAVIGATION = 'NAVIGATION'
  398.     
  399.     def __init__(self):
  400.         pass
  401.  
  402.  
  403.  
  404. def keyEcho(event):
  405.     '''If the keyEcho setting is enabled, check to see what type of key
  406.     event it is and echo it via speech, if the user wants that type of
  407.     key echoed.
  408.  
  409.     Uppercase keys will be spoken using the "uppercase" voice style,
  410.     whereas lowercase keys will be spoken using the "default" voice style.
  411.  
  412.     Arguments:
  413.     - event: an AT-SPI DeviceEvent
  414.     '''
  415.     if orca_state.locusOfFocus and orca_state.locusOfFocus.getRole() == pyatspi.ROLE_PASSWORD_TEXT:
  416.         return None
  417.     event_string = event.event_string
  418.     debug.println(debug.LEVEL_FINEST, 'orca.keyEcho: string to echo: %s' % event_string)
  419.     if settings.enableKeyEcho:
  420.         if isModifierKey(event_string):
  421.             if not settings.enableModifierKeys:
  422.                 return None
  423.             eventType = KeyEventType.MODIFIER
  424.         elif isNavigationKey(event_string):
  425.             if not settings.enableNavigationKeys:
  426.                 return None
  427.             eventType = KeyEventType.NAVIGATION
  428.         elif isPrintableKey(event_string):
  429.             if not settings.enablePrintableKeys:
  430.                 return None
  431.             eventType = KeyEventType.PRINTABLE
  432.         elif isLockingKey(event_string):
  433.             if not settings.enableLockingKeys:
  434.                 return None
  435.             eventType = KeyEventType.LOCKING
  436.             modifiers = event.modifiers
  437.             if event_string == 'Caps_Lock':
  438.                 if modifiers & 1 << pyatspi.MODIFIER_SHIFTLOCK:
  439.                     eventType = KeyEventType.LOCKING_UNLOCKED
  440.                 else:
  441.                     eventType = KeyEventType.LOCKING_LOCKED
  442.             elif event_string == 'Num_Lock':
  443.                 pass
  444.             
  445.         elif isFunctionKey(event_string):
  446.             if not settings.enableFunctionKeys:
  447.                 return None
  448.             eventType = KeyEventType.FUNCTION
  449.         elif isActionKey(event_string):
  450.             if not settings.enableActionKeys:
  451.                 return None
  452.             eventType = KeyEventType.ACTION
  453.         else:
  454.             debug.println(debug.LEVEL_FINEST, 'orca.keyEcho: event string not handled: %s' % event_string)
  455.             return None
  456.         settings.enableActionKeys.println(debug.LEVEL_FINEST, 'orca.keyEcho: speaking: %s' % event_string)
  457.         orca_state.lastKeyEchoTime = time.time()
  458.         speech.speakKeyEvent(event_string, eventType)
  459.     
  460.  
  461.  
  462. def _setClickCount(inputEvent):
  463.     '''Sets the count of the number of clicks a user has made to one
  464.     of the non-modifier keys on the keyboard.  Note that this looks at
  465.     the event_string (keysym) instead of hw_code (keycode) because
  466.     the Java platform gives us completely different keycodes for keys.
  467.  
  468.     Arguments:
  469.     - inputEvent: the current input event.
  470.     '''
  471.     lastInputEvent = orca_state.lastNonModifierKeyEvent
  472.     if inputEvent.type == pyatspi.KEY_RELEASED_EVENT:
  473.         pass
  474.     elif not isinstance(inputEvent, KeyboardEvent):
  475.         orca_state.clickCount = 0
  476.     elif not isinstance(lastInputEvent, KeyboardEvent):
  477.         orca_state.clickCount = 1
  478.     elif lastInputEvent.event_string != inputEvent.event_string or lastInputEvent.modifiers != inputEvent.modifiers:
  479.         orca_state.clickCount = 1
  480.     elif inputEvent.time - lastInputEvent.time < settings.doubleClickTimeout:
  481.         if orca_state.clickCount < 3:
  482.             orca_state.clickCount += 1
  483.         
  484.     else:
  485.         orca_state.clickCount = 1
  486.  
  487.  
  488. def _processKeyCaptured(event):
  489.     '''Called when a new key event arrives and orca_state.capturingKeys=True.
  490.     (used for key bindings redefinition)
  491.     '''
  492.     if event.type == 0:
  493.         if isModifierKey(event.event_string) or isLockingKey(event.event_string):
  494.             return True
  495.         keymap = gtk.gdk.keymap_get_default()
  496.         entries = keymap.get_entries_for_keycode(event.hw_code)
  497.         event.event_string = gtk.gdk.keyval_name(entries[0][0])
  498.         if event.event_string.startswith('KP') and event.event_string != 'KP_Enter':
  499.             name = gtk.gdk.keyval_name(entries[1][0])
  500.             if name.startswith('KP'):
  501.                 event.event_string = name
  502.             
  503.         
  504.         orca_state.lastCapturedKey = event
  505.     
  506.     return False
  507.  
  508.  
  509. def _processKeyboardEvent(event):
  510.     '''The primary key event handler for Orca.  Keeps track of various
  511.     attributes, such as the lastInputEvent.  Also calls keyEcho as well
  512.     as any local keybindings before passing the event on to the active
  513.     presentation manager.  This method is called synchronously from the
  514.     AT-SPI registry and should be performant.  In addition, it
  515.     must return True if it has consumed the event (and False if not).
  516.  
  517.     Arguments:
  518.     - event: an AT-SPI DeviceEvent
  519.  
  520.     Returns True if the event should be consumed.
  521.     '''
  522.     global _orcaModifierPressed, _orcaModifierPressed
  523.     orca_state.lastInputEventTimestamp = event.timestamp
  524.     string = keyEventToString(event)
  525.     debug.printInputEvent(debug.LEVEL_FINE, string)
  526.     keyboardEvent = KeyboardEvent(event)
  527.     if False:
  528.         allPossibleKeysyms = []
  529.         for keysym in settings.orcaModifierKeys:
  530.             allPossibleKeysyms.extend(keybindings.getAllKeysyms(keysym))
  531.         
  532.     else:
  533.         allPossibleKeysyms = settings.orcaModifierKeys
  534.     isOrcaModifier = allPossibleKeysyms.count(keyboardEvent.event_string) > 0
  535.     if event.type == pyatspi.KEY_PRESSED_EVENT:
  536.         speech.stop()
  537.         if isOrcaModifier:
  538.             _orcaModifierPressed = True
  539.         
  540.         if not (settings.learnModeEnabled) and orca_state.activeScript.echoKey(keyboardEvent):
  541.             keyEcho(keyboardEvent)
  542.         
  543.     elif isOrcaModifier and keyboardEvent.type == pyatspi.KEY_RELEASED_EVENT:
  544.         _orcaModifierPressed = False
  545.     
  546.     if _orcaModifierPressed:
  547.         keyboardEvent.modifiers = keyboardEvent.modifiers | settings.ORCA_MODIFIER_MASK
  548.     
  549.     orca_state.lastInputEvent = keyboardEvent
  550.     if not isModifierKey(keyboardEvent.event_string):
  551.         _setClickCount(keyboardEvent)
  552.         orca_state.lastNonModifierKeyEvent = keyboardEvent
  553.     
  554.     consumed = False
  555.     
  556.     try:
  557.         if orca_state.capturingKeys:
  558.             consumed = _processKeyCaptured(keyboardEvent)
  559.         else:
  560.             consumed = _keyBindings.consumeKeyboardEvent(None, keyboardEvent)
  561.             if not consumed and _currentPresentationManager >= 0:
  562.                 consumed = _PRESENTATION_MANAGERS[_currentPresentationManager].processKeyboardEvent(keyboardEvent)
  563.             
  564.             if not consumed and settings.learnModeEnabled:
  565.                 if keyboardEvent.type == pyatspi.KEY_PRESSED_EVENT:
  566.                     clickCount = orca_state.activeScript.getClickCount()
  567.                     if isPrintableKey(keyboardEvent.event_string) and clickCount == 2:
  568.                         orca_state.activeScript.phoneticSpellCurrentItem(keyboardEvent.event_string)
  569.                     else:
  570.                         braille.displayMessage(keyboardEvent.event_string)
  571.                         event_string = keyboardEvent.event_string
  572.                         event_string = keynames.getKeyName(event_string)
  573.                         speech.speak(event_string)
  574.                 elif event.type == pyatspi.KEY_RELEASED_EVENT and keyboardEvent.event_string == 'Escape':
  575.                     exitLearnMode(keyboardEvent)
  576.                 
  577.                 consumed = True
  578.             
  579.             if not consumed and not isModifierKey(keyboardEvent.event_string) and keyboardEvent.type == pyatspi.KEY_PRESSED_EVENT:
  580.                 orca_state.bypassNextCommand = False
  581.     except:
  582.         debug.printException(debug.LEVEL_SEVERE)
  583.     
  584.  
  585.     if not consumed:
  586.         pass
  587.     return isOrcaModifier
  588.  
  589.  
  590. def _processBrailleEvent(command):
  591.     '''Called whenever a  key is pressed on the Braille display.
  592.  
  593.     Arguments:
  594.     - command: the BrlAPI command for the key that was pressed.
  595.  
  596.     Returns True if the event was consumed; otherwise False
  597.     '''
  598.     consumed = False
  599.     speech.stop()
  600.     event = BrailleEvent(command)
  601.     orca_state.lastInputEvent = event
  602.     
  603.     try:
  604.         consumed = _PRESENTATION_MANAGERS[_currentPresentationManager].processBrailleEvent(event)
  605.     except:
  606.         debug.printException(debug.LEVEL_SEVERE)
  607.  
  608.     if not consumed and settings.learnModeEnabled:
  609.         consumed = True
  610.     
  611.     return consumed
  612.  
  613.  
  614. def toggleSilenceSpeech(script = None, inputEvent = None):
  615.     '''Toggle the silencing of speech.
  616.  
  617.     Returns True to indicate the input event has been consumed.
  618.     '''
  619.     speech.stop()
  620.     if settings.silenceSpeech:
  621.         settings.silenceSpeech = False
  622.         speech.speak(_('Speech enabled.'))
  623.     else:
  624.         speech.speak(_('Speech disabled.'))
  625.         settings.silenceSpeech = True
  626.     return True
  627.  
  628.  
  629. def loadUserSettings(script = None, inputEvent = None):
  630.     '''Loads (and reloads) the user settings module, reinitializing
  631.     things such as speech if necessary.
  632.  
  633.     Returns True to indicate the input event has been consumed.
  634.     '''
  635.     global _userSettings
  636.     if settings.useDBus:
  637.         dbusserver.shutdown()
  638.     
  639.     httpserver.shutdown()
  640.     speech.shutdown()
  641.     braille.shutdown()
  642.     mag.shutdown()
  643.     if _currentPresentationManager >= 0:
  644.         _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()
  645.     
  646.     time.sleep(1)
  647.     reloaded = False
  648.     if _userSettings:
  649.         
  650.         try:
  651.             reload(_userSettings)
  652.             reloaded = True
  653.         except ImportError:
  654.             debug.printException(debug.LEVEL_FINEST)
  655.         except:
  656.             None<EXCEPTION MATCH>ImportError
  657.             debug.printException(debug.LEVEL_SEVERE)
  658.         
  659.  
  660.     None<EXCEPTION MATCH>ImportError
  661.     
  662.     try:
  663.         _userSettings = __import__('user-settings')
  664.     except ImportError:
  665.         debug.printException(debug.LEVEL_FINEST)
  666.     except:
  667.         debug.printException(debug.LEVEL_SEVERE)
  668.  
  669.     for key in _commandLineSettings:
  670.         setattr(settings, key, _commandLineSettings[key])
  671.     
  672.     if settings.enableSpeech:
  673.         
  674.         try:
  675.             speech.init()
  676.             if reloaded:
  677.                 speech.speak(_('Orca user settings reloaded.'))
  678.             
  679.             debug.println(debug.LEVEL_CONFIGURATION, 'Speech module has been initialized.')
  680.         debug.printException(debug.LEVEL_SEVERE)
  681.         debug.println(debug.LEVEL_SEVERE, 'Could not initialize connection to speech.')
  682.  
  683.     else:
  684.         debug.println(debug.LEVEL_CONFIGURATION, 'Speech module has NOT been initialized.')
  685.     if settings.enableBraille:
  686.         
  687.         try:
  688.             braille.init(_processBrailleEvent, settings.tty)
  689.         debug.printException(debug.LEVEL_WARNING)
  690.         debug.println(debug.LEVEL_WARNING, 'Could not initialize connection to braille.')
  691.  
  692.     
  693.     if settings.enableMagnifier:
  694.         
  695.         try:
  696.             mag.init()
  697.             debug.println(debug.LEVEL_CONFIGURATION, 'Magnification module has been initialized.')
  698.         debug.printException(debug.LEVEL_SEVERE)
  699.         debug.println(debug.LEVEL_SEVERE, 'Could not initialize connection to magnifier.')
  700.  
  701.     else:
  702.         debug.println(debug.LEVEL_CONFIGURATION, 'Magnification module has NOT been initialized.')
  703.     
  704.     try:
  705.         mouse_review.mouse_reviewer.toggle(on = settings.enableMouseReview)
  706.     except NameError:
  707.         pass
  708.  
  709.     for keyName in settings.orcaModifierKeys:
  710.         if keyName == 'Caps_Lock':
  711.             os.system('xmodmap -e "clear Lock"')
  712.         
  713.         if keyName in ('Caps_Lock', 'KP_Insert', 'Insert'):
  714.             command = 'xmodmap -e "keysym %s = %s"' % (keyName, keyName)
  715.             os.system(command)
  716.             continue
  717.     
  718.     if _currentPresentationManager >= 0:
  719.         _PRESENTATION_MANAGERS[_currentPresentationManager].activate()
  720.     
  721.     showMainWindowGUI()
  722.     if settings.useDBus:
  723.         dbusserver.init()
  724.     
  725.     httpserver.init()
  726.     return True
  727.  
  728.  
  729. def showAppPreferencesGUI(script = None, inputEvent = None):
  730.     '''Displays the user interace to configure the settings for a
  731.     specific applications within Orca and set up those app-specific
  732.     user preferences using a GUI.
  733.  
  734.     Returns True to indicate the input event has been consumed.
  735.     '''
  736.     
  737.     try:
  738.         module = __import__(settings.appGuiPreferencesModule, globals(), locals(), [
  739.             ''])
  740.         module.showPreferencesUI()
  741.     except:
  742.         debug.printException(debug.LEVEL_SEVERE)
  743.  
  744.     return True
  745.  
  746.  
  747. def showPreferencesGUI(script = None, inputEvent = None):
  748.     '''Displays the user interace to configure Orca and set up
  749.     user preferences using a GUI.
  750.  
  751.     Returns True to indicate the input event has been consumed.
  752.     '''
  753.     
  754.     try:
  755.         module = __import__(settings.guiPreferencesModule, globals(), locals(), [
  756.             ''])
  757.         module.showPreferencesUI()
  758.     except:
  759.         debug.printException(debug.LEVEL_SEVERE)
  760.  
  761.     return True
  762.  
  763.  
  764. def showMainWindowGUI(script = None, inputEvent = None):
  765.     '''Displays the Orca main window.
  766.  
  767.     Returns True to indicate the input event has been consumed.
  768.     '''
  769.     
  770.     try:
  771.         module = __import__(settings.mainWindowModule, globals(), locals(), [
  772.             ''])
  773.         if settings.showMainWindow:
  774.             module.showMainUI()
  775.         else:
  776.             module.hideMainUI()
  777.     except:
  778.         debug.printException(debug.LEVEL_SEVERE)
  779.  
  780.     return True
  781.  
  782.  
  783. def _showPreferencesConsole(script = None, inputEvent = None):
  784.     '''Displays the user interace to configure Orca and set up
  785.     user preferences via a command line interface.
  786.  
  787.     Returns True to indicate the input event has been consumed.
  788.     '''
  789.     
  790.     try:
  791.         module = __import__(settings.consolePreferencesModule, globals(), locals(), [
  792.             ''])
  793.         module.showPreferencesUI(_commandLineSettings)
  794.     except:
  795.         debug.printException(debug.LEVEL_SEVERE)
  796.  
  797.     return True
  798.  
  799.  
  800. def helpForOrca(script = None, inputEvent = None):
  801.     '''Show Orca Help window (part of the GNOME Access Guide).
  802.  
  803.     Returns True to indicate the input event has been consumed.
  804.     '''
  805.     props = {
  806.         gnome.PARAM_APP_DATADIR: '/usr/share' }
  807.     prog = gnome.program_init('orca', '1.0', properties = props)
  808.     gnome.help_display_with_doc_id(prog, 'gnome-access-guide', 'gnome-access-guide', 'ats-2')
  809.     return True
  810.  
  811.  
  812. def quitOrca(script = None, inputEvent = None):
  813.     '''Quit Orca. Check if the user wants to confirm this action.
  814.     If so, show the confirmation GUI otherwise just shutdown.
  815.  
  816.     Returns True to indicate the input event has been consumed.
  817.     '''
  818.     if settings.quitOrcaNoConfirmation:
  819.         shutdown()
  820.     else:
  821.         
  822.         try:
  823.             module = __import__(settings.quitModule, globals(), locals(), [
  824.                 ''])
  825.             module.showQuitUI()
  826.         except:
  827.             debug.printException(debug.LEVEL_SEVERE)
  828.  
  829.     return True
  830.  
  831.  
  832. def showFindGUI(script = None, inputEvent = None):
  833.     '''Displays the user interace to perform an Orca Find.
  834.  
  835.     Returns True to indicate the input event has been consumed.
  836.     '''
  837.     
  838.     try:
  839.         module = __import__(settings.findModule, globals(), locals(), [
  840.             ''])
  841.         module.showFindUI()
  842.     except:
  843.         debug.printException(debug.LEVEL_SEVERE)
  844.  
  845.  
  846. _initialized = False
  847.  
  848. def init(registry):
  849.     '''Initialize the orca module, which initializes speech, braille,
  850.     and mag modules.  Also builds up the application list, registers
  851.     for AT-SPI events, and creates scripts for all known applications.
  852.  
  853.     Returns True if the initialization procedure has run, or False if this
  854.     module has already been initialized.
  855.     '''
  856.     global _keyBindings, _initialized
  857.     if _initialized:
  858.         return False
  859.     if settings.timeoutCallback and settings.timeoutTime > 0:
  860.         signal.signal(signal.SIGALRM, settings.timeoutCallback)
  861.         signal.alarm(settings.timeoutTime)
  862.     
  863.     _keyBindings = keybindings.KeyBindings()
  864.     registry.registerEventListener(_onChildrenChanged, 'object:children-changed')
  865.     registry.registerEventListener(_onMouseButton, 'mouse:button')
  866.     loadUserSettings()
  867.     masks = []
  868.     mask = 0
  869.     while mask <= 255:
  870.         masks.append(mask)
  871.         mask += 1
  872.     pyatspi.Registry.registerKeystrokeListener(_processKeyboardEvent, mask = masks, kind = (pyatspi.KEY_PRESSED_EVENT, pyatspi.KEY_RELEASED_EVENT))
  873.     if settings.timeoutCallback and settings.timeoutTime > 0:
  874.         signal.alarm(0)
  875.     
  876.     _initialized = True
  877.     return True
  878.  
  879.  
  880. def start(registry):
  881.     '''Starts Orca.
  882.     '''
  883.     global _PRESENTATION_MANAGERS
  884.     if not _initialized:
  885.         init(registry)
  886.     
  887.     if settings.timeoutCallback and settings.timeoutTime > 0:
  888.         signal.signal(signal.SIGALRM, settings.timeoutCallback)
  889.         signal.alarm(settings.timeoutTime)
  890.     
  891.     if not _PRESENTATION_MANAGERS:
  892.         import focus_tracking_presenter
  893.         _PRESENTATION_MANAGERS = [
  894.             focus_tracking_presenter.FocusTrackingPresenter()]
  895.     
  896.     _switchToPresentationManager(0)
  897.     if settings.timeoutCallback and settings.timeoutTime > 0:
  898.         signal.alarm(0)
  899.     
  900.     if settings.cacheValues:
  901.         pyatspi.setCacheLevel(pyatspi.CACHE_PROPERTIES)
  902.     
  903.     registry.start()
  904.  
  905.  
  906. def die(exitCode = 1):
  907.     os._exit(exitCode)
  908.  
  909.  
  910. def timeout(signum = None, frame = None):
  911.     debug.println(debug.LEVEL_SEVERE, 'TIMEOUT: something has hung.  Aborting.')
  912.     debug.printStack(debug.LEVEL_ALL)
  913.     die(50)
  914.  
  915.  
  916. def shutdown(script = None, inputEvent = None):
  917.     '''Exits Orca.  Unregisters any event listeners and cleans up.  Also
  918.     quits the bonobo main loop and resets the initialized state to False.
  919.  
  920.     Returns True if the shutdown procedure ran or False if this module
  921.     was never initialized.
  922.     '''
  923.     global _initialized
  924.     if not _initialized:
  925.         return False
  926.     if settings.timeoutCallback and settings.timeoutTime > 0:
  927.         signal.signal(signal.SIGALRM, settings.timeoutCallback)
  928.         signal.alarm(settings.timeoutTime)
  929.     
  930.     speech.speak(_('Goodbye.'))
  931.     braille.displayMessage(_('Goodbye.'))
  932.     pyatspi.Registry.deregisterEventListener(_onChildrenChanged, 'object:children-changed')
  933.     pyatspi.Registry.deregisterEventListener(_onMouseButton, 'mouse:button')
  934.     if _currentPresentationManager >= 0:
  935.         _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()
  936.     
  937.     if settings.enableSpeech:
  938.         speech.shutdown()
  939.     
  940.     if settings.enableBraille:
  941.         braille.shutdown()
  942.     
  943.     if settings.enableMagnifier or settings.enableMagLiveUpdating:
  944.         mag.shutdown()
  945.     
  946.     pyatspi.Registry.stop()
  947.     if settings.timeoutCallback and settings.timeoutTime > 0:
  948.         signal.alarm(0)
  949.     
  950.     _initialized = False
  951.     return True
  952.  
  953. exitCount = 0
  954.  
  955. def shutdownOnSignal(signum, frame):
  956.     global exitCount
  957.     debug.println(debug.LEVEL_ALL, 'Shutting down and exiting due to signal = %d' % signum)
  958.     debug.println(debug.LEVEL_ALL, 'Current stack is:')
  959.     debug.printStack(debug.LEVEL_ALL)
  960.     if exitCount:
  961.         die(signum)
  962.     else:
  963.         exitCount += 1
  964.     if settings.timeoutCallback and settings.timeoutTime > 0:
  965.         signal.signal(signal.SIGALRM, settings.timeoutCallback)
  966.         signal.alarm(settings.timeoutTime)
  967.     
  968.     
  969.     try:
  970.         if _initialized:
  971.             shutdown()
  972.         else:
  973.             speech.shutdown()
  974.             shutdown()
  975.         cleanExit = True
  976.     except:
  977.         cleanExit = False
  978.  
  979.     if settings.timeoutCallback and settings.timeoutTime > 0:
  980.         signal.alarm(0)
  981.     
  982.     if not cleanExit:
  983.         die(signum)
  984.     
  985.  
  986.  
  987. def abortOnSignal(signum, frame):
  988.     debug.println(debug.LEVEL_ALL, 'Aborting due to signal = %d' % signum)
  989.     die(signum)
  990.  
  991.  
  992. def usage():
  993.     '''Prints out usage information.'''
  994.     print _('Usage: orca [OPTION...]')
  995.     print 
  996.     print '-?, --help                   ' + _('Show this help message')
  997.     print '-v, --version                %s' % platform.version
  998.     print '-l, --list-apps              ' + _('Print the known running applications')
  999.     print '-s, --setup, --gui-setup     ' + _('Set up user preferences')
  1000.     print '-t, --text-setup             ' + _('Set up user preferences (text version)')
  1001.     print '-n, --no-setup               ' + _('Skip set up of user preferences')
  1002.     print '-u, --user-prefs-dir=dirname ' + _('Use alternate directory for user preferences')
  1003.     print '-e, --enable=[speech' + '|' + 'braille' + '|' + 'braille-monitor' + '|' + 'magnifier' + '|' + 'main-window' + ']', _('Force use of option')
  1004.     print '-d, --disable=[' + 'speech' + '|' + 'braille' + '|' + 'braille-monitor' + '|' + 'magnifier' + '|' + 'main-window' + ']', _('Prevent use of option')
  1005.     print '-q, --quit                   ' + _('Quits Orca (if shell script used)')
  1006.     print 
  1007.     print _('If Orca has not been previously set up by the user, Orca\nwill automatically launch the preferences set up unless\nthe -n or --no-setup option is used.')
  1008.     print 
  1009.     print _('WARNING: suspending Orca, e.g. by pressing Control-Z, from\nan AT-SPI enabled shell (such as gnome-terminal), can also\nsuspend the desktop until Orca is killed.')
  1010.     print 
  1011.     print _('Report bugs to orca-list@gnome.org.')
  1012.  
  1013.  
  1014. def main():
  1015.     '''The main entry point for Orca.  The exit codes for Orca will
  1016.     loosely be based on signals, where the exit code will be the
  1017.     signal used to terminate Orca (if a signal was used).  Otherwise,
  1018.     an exit code of 0 means normal completion and an exit code of 50
  1019.     means Orca exited because of a hang.'''
  1020.     settings.timeoutCallback = timeout
  1021.     signal.signal(signal.SIGHUP, shutdownOnSignal)
  1022.     signal.signal(signal.SIGINT, shutdownOnSignal)
  1023.     signal.signal(signal.SIGTERM, shutdownOnSignal)
  1024.     signal.signal(signal.SIGQUIT, shutdownOnSignal)
  1025.     signal.signal(signal.SIGSEGV, abortOnSignal)
  1026.     desktopRunning = False
  1027.     
  1028.     try:
  1029.         if gtk.gdk.display_get_default():
  1030.             desktopRunning = True
  1031.     except:
  1032.         pass
  1033.  
  1034.     bypassSetup = False
  1035.     setupRequested = False
  1036.     showGUI = False
  1037.     arglist = sys.argv[1:]
  1038.     if len(arglist) == 1:
  1039.         arglist = arglist[0].split()
  1040.     
  1041.     
  1042.     try:
  1043.         (opts, args) = getopt.getopt(arglist, '?stnvld:e:u:', [
  1044.             'help',
  1045.             'user-prefs-dir=',
  1046.             'enable=',
  1047.             'disable=',
  1048.             'setup',
  1049.             'gui-setup',
  1050.             'text-setup',
  1051.             'no-setup',
  1052.             'list-apps',
  1053.             'version'])
  1054.         for opt, val in opts:
  1055.             if opt in ('-u', '--user-prefs-dir'):
  1056.                 userPrefsDir = val.strip()
  1057.                 
  1058.                 try:
  1059.                     os.chdir(userPrefsDir)
  1060.                     settings.userPrefsDir = userPrefsDir
  1061.                 debug.printException(debug.LEVEL_FINEST)
  1062.  
  1063.             
  1064.             if opt in ('-e', '--enable'):
  1065.                 feature = val.strip()
  1066.                 if feature == 'speech':
  1067.                     _commandLineSettings['enableSpeech'] = True
  1068.                 elif feature == 'braille':
  1069.                     _commandLineSettings['enableBraille'] = True
  1070.                 elif feature == 'braille-monitor':
  1071.                     _commandLineSettings['enableBrailleMonitor'] = True
  1072.                 elif feature == 'magnifier':
  1073.                     _commandLineSettings['enableMagnifier'] = True
  1074.                 elif feature == 'main-window':
  1075.                     _commandLineSettings['showMainWindow'] = True
  1076.                 else:
  1077.                     usage()
  1078.                     die(2)
  1079.             
  1080.             if opt in ('-d', '--disable'):
  1081.                 feature = val.strip()
  1082.                 if feature == 'speech':
  1083.                     _commandLineSettings['enableSpeech'] = False
  1084.                 elif feature == 'braille':
  1085.                     _commandLineSettings['enableBraille'] = False
  1086.                 elif feature == 'braille-monitor':
  1087.                     _commandLineSettings['enableBrailleMonitor'] = False
  1088.                 elif feature == 'magnifier':
  1089.                     _commandLineSettings['enableMagnifier'] = False
  1090.                 elif feature == 'main-window':
  1091.                     _commandLineSettings['showMainWindow'] = False
  1092.                 else:
  1093.                     usage()
  1094.                     die(2)
  1095.             
  1096.             if opt in ('-s', '--gui-setup', '--setup'):
  1097.                 setupRequested = True
  1098.                 showGUI = desktopRunning
  1099.             
  1100.             if opt in ('-t', '--text-setup'):
  1101.                 setupRequested = True
  1102.                 showGUI = False
  1103.             
  1104.             if opt in ('-n', '--no-setup'):
  1105.                 bypassSetup = True
  1106.             
  1107.             if opt in ('-?', '--help'):
  1108.                 usage()
  1109.                 die(0)
  1110.             
  1111.             if opt in ('-v', '--version'):
  1112.                 print 'Orca %s' % platform.version
  1113.                 die(0)
  1114.             
  1115.             if opt in ('-l', '--list-apps'):
  1116.                 apps = filter((lambda x: x is not None), pyatspi.Registry.getDesktop(0))
  1117.                 for app in apps:
  1118.                     print app.name
  1119.                 
  1120.                 die(0)
  1121.                 continue
  1122.     except:
  1123.         debug.printException(debug.LEVEL_OFF)
  1124.         usage()
  1125.         die(2)
  1126.  
  1127.     a11yEnabled = settings.isAccessibilityEnabled()
  1128.     if not bypassSetup and not a11yEnabled:
  1129.         _showPreferencesConsole()
  1130.         die()
  1131.     
  1132.     if setupRequested and not bypassSetup and not showGUI:
  1133.         _showPreferencesConsole()
  1134.     
  1135.     if not desktopRunning:
  1136.         print 'Cannot start Orca because it cannot connect'
  1137.         print 'to the Desktop.  Please make sure the DISPLAY'
  1138.         print 'environment variable has been set.'
  1139.         return 1
  1140.     userprefs = settings.userPrefsDir
  1141.     sys.path.insert(0, userprefs)
  1142.     sys.path.insert(0, '')
  1143.     init(pyatspi.Registry)
  1144.     
  1145.     try:
  1146.         message = _('Welcome to Orca.')
  1147.         speech.speak(message)
  1148.         braille.displayMessage(message)
  1149.     except:
  1150.         desktopRunning
  1151.         debug.printException(debug.LEVEL_SEVERE)
  1152.  
  1153.     if setupRequested and not bypassSetup and showGUI:
  1154.         showPreferencesGUI()
  1155.     elif not _userSettings and not bypassSetup:
  1156.         if desktopRunning:
  1157.             showPreferencesGUI()
  1158.         else:
  1159.             _showPreferencesConsole()
  1160.     
  1161.     start(pyatspi.Registry)
  1162.     return 0
  1163.  
  1164. if __name__ == '__main__':
  1165.     sys.exit(main())
  1166.  
  1167.